﻿using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Web;

namespace Easy.Web.CMS.Data
{
    public static class DataExtensions
    {
        public static string GetJsonString(this DataSet ds)
        {
            string json = string.Empty;
            IList<Hashtable> mList = new List<Hashtable>();
            try
            {
                foreach (DataRow row in ds.Tables[0].Rows)
                {
                    Hashtable ht = new Hashtable();
                    foreach (DataColumn col in ds.Tables[0].Columns)
                    {
                        ht.Add(col.ColumnName, row[col.ColumnName]);
                    }
                    mList.Add(ht);
                }
                json = JsonConvert.SerializeObject(mList);
            }
            catch (Exception ex)
            {
                string error = ex.Message;
            }
            return json;
        }

        public static string GetJsonString(this DataSet ds,string dateformat)
        {
            string json = string.Empty;
            IList<Hashtable> mList = new List<Hashtable>();
            try
            {
                foreach (DataRow row in ds.Tables[0].Rows)
                {
                    Hashtable ht = new Hashtable();
                    foreach (DataColumn col in ds.Tables[0].Columns)
                    {
                        ht.Add(col.ColumnName, row[col.ColumnName]);
                    }
                    mList.Add(ht);
                }
                json = JsonConvert.SerializeObject(mList, Formatting.Indented, new IsoDateTimeConverter()
                {
                    DateTimeFormat = string.IsNullOrEmpty(dateformat) ? "MM-dd" : dateformat
                });
            }
            catch (Exception ex)
            {
                string error = ex.Message;
            }
            return json;
        }

        public static bool HasData(this DataSet ds)
        {
            return ds != null && ds.Tables != null && ds.Tables[0] != null ? true : false;
        }

        public static List<T> RemoveNull<T>(this List<T> list)
        {
            // 找出第一个空元素 O(n)
            int count = list.Count;
            for (int i = 0; i < count; i++)
            {
                if (list[i] == null)
                {
                    // 记录当前位置
                    int newCount = i++;

                    // 对每个非空元素，复制至当前位置 O(n)
                    for (; i < count; i++)
                        if (list[i] != null)
                            list[newCount++] = list[i];

                    // 移除多余的元素 O(n)
                    list.RemoveRange(newCount, count - newCount);
                    break;
                }
            }
            return list;
        }

        public static string CutString(this string str, int length)
        {
            str = str.Trim();
            if (str == null || str.Length == 0 || length <= 0)
            {
                return string.Empty;
            }
            if (str.Length > length)
            {
                int i;
                for (i = 0; i < length; i++)
                {
                    if (str[i] > '\u0080')
                    {
                        length--;
                    }
                }
                return str.Substring(0, i) + "...";
            }
            return str;
        }

        public static string GetSubString(this string origStr, int endIndex)
        {
            if (origStr == null || origStr.Length == 0 || endIndex < 0)
                return "";
            int bytesCount = System.Text.Encoding.GetEncoding("gb2312").GetByteCount(origStr);
            if (bytesCount > endIndex)
            {
                int readyLength = 0;
                int byteLength;
                for (int i = 0; i < origStr.Length; i++)
                {
                    byteLength = System.Text.Encoding.GetEncoding("gb2312").GetByteCount(new char[] { origStr[i] });
                    readyLength += byteLength;
                    if (readyLength == endIndex)
                    {
                        origStr = origStr.Substring(0, i + 1) + "...";
                        break;
                    }
                    else if (readyLength > endIndex)
                    {
                        origStr = origStr.Substring(0, i) + "...";
                        break;
                    }
                }
            }
            return origStr;
        }

        /// <summary>
        /// 过滤html标签
        /// </summary>
        /// <param name="Htmlstring"></param>
        /// <returns></returns>
        public static string ParseTags(this string Htmlstring)
        {
            //删除脚本  
            Htmlstring = Regex.Replace(Htmlstring, @"<script[^>]*?>.*?</script>", "", RegexOptions.IgnoreCase);
            //删除<style></style>样式
            Htmlstring = Regex.Replace(Htmlstring, @"<style[^>]*?>[\s\S]*?</style>", "", RegexOptions.IgnoreCase);
            //删除HTML  
            Htmlstring = Regex.Replace(Htmlstring, @"<(.[^>]*)>", "", RegexOptions.IgnoreCase);
            Htmlstring = Regex.Replace(Htmlstring, @"([\r\n])[\s]+", "", RegexOptions.IgnoreCase);
            Htmlstring = Regex.Replace(Htmlstring, @"-->", "", RegexOptions.IgnoreCase);
            Htmlstring = Regex.Replace(Htmlstring, @"<!--.*", "", RegexOptions.IgnoreCase);
            Htmlstring = Regex.Replace(Htmlstring, @"&(quot|#34);", "\"", RegexOptions.IgnoreCase);
            Htmlstring = Regex.Replace(Htmlstring, @"&(amp|#38);", "&", RegexOptions.IgnoreCase);
            Htmlstring = Regex.Replace(Htmlstring, @"&(lt|#60);", "<", RegexOptions.IgnoreCase);
            Htmlstring = Regex.Replace(Htmlstring, @"&(gt|#62);", ">", RegexOptions.IgnoreCase);
            Htmlstring = Regex.Replace(Htmlstring, @"&(nbsp|#160);", " ", RegexOptions.IgnoreCase);
            Htmlstring = Regex.Replace(Htmlstring, @"&(iexcl|#161);", "\xa1", RegexOptions.IgnoreCase);
            Htmlstring = Regex.Replace(Htmlstring, @"&(cent|#162);", "\xa2", RegexOptions.IgnoreCase);
            Htmlstring = Regex.Replace(Htmlstring, @"&(pound|#163);", "\xa3", RegexOptions.IgnoreCase);
            Htmlstring = Regex.Replace(Htmlstring, @"&(copy|#169);", "\xa9", RegexOptions.IgnoreCase); Htmlstring = Regex.Replace(Htmlstring, @"&#(\d+);", "", RegexOptions.IgnoreCase);
            Htmlstring.Replace("<", "");
            Htmlstring.Replace(">", "");
            Htmlstring.Replace("\r\n", "");
            Htmlstring = HttpContext.Current.Server.HtmlEncode(Htmlstring).Trim();
            return Htmlstring;
        }

        private static string GetOper(Condition<object> item)
        {
            string oper = "";
            switch (item.Operation.ToUpper())
            {
                case "EQ":
                    oper = "=";
                    break;
                case "NE":
                    oper = "!=";
                    break;
                case "IN":
                    oper = "IN";
                    break;
                case "LIKE":
                    oper = "LIKE";
                    break;
                case "LT":
                    oper = "<";
                    break;
                case "LTE":
                    oper = "<=";
                    break;
                case "GT":
                    oper = ">";
                    break;
                case "GTE":
                    oper = ">=";
                    break;
                default:
                    break;
            }
            return oper;
        }

        public static string GetCondition(this List<Condition<object>> conditions, WhereType type)
        {
            string where = string.Empty;
            if (conditions != null && conditions.Count > 0)
            {
                string start = " and ( ";
                string end = " ) ";
                int count = 0;

                foreach (var item in conditions)
                {
                    if (string.IsNullOrEmpty(item.Operation)) continue;
                    string oper = GetOper(item);

                    string value = item.Value.ToString();
                    string field = item.Name;
                    if (!field.Trim().StartsWith("["))
                    {
                         field = "[" + field + "]";  //所有的字段添加中括号
                    }

                    if (count == 0)
                    {
                        where = where + start;
                    }
                    else
                    {
                        where = where + (type == WhereType.And ? " and " : " or ");
                    }

                    if (oper == "IN")
                    {
                        value = string.IsNullOrEmpty(item.Value.ToString()) ? "" :
                                 "('" + string.Join("','", item.Value.ToString().Split(new string[] { ",", "|" }, StringSplitOptions.RemoveEmptyEntries)) + "')";
                        where = where + field + " in" + value;
                    }
                    else if (oper == "LIKE")
                    {
                        value = "%" + item.Value.ToString() + "%";    // '%模糊查询%'
                        where = where + field + " like " + value;
                    }
                    else
                    {
                        if (item.ValueType == "NumberComponent")
                        {
                            where = where + field + " " + oper + " " + value;
                        }
                        else
                        {
                            where = where + field + " " + oper + " '" + value + "'";
                        }
                    }

                    if (count == conditions.Count - 1)
                    {
                        where = where + end;
                    }

                    count++;
                }
            }
            return where;
        }

        public static QueryParameter AsQueryParameter(this string b)
        {
            return new QueryParameter(b);
        }
        public static QueryParameter AsQueryParameter(this DBNull b)
        {
            return new QueryParameter(b);
        }
    }

    public enum WhereType
    {
        And,
        Or
    }

    public class Condition<T>
    {
        public string Name { get; set; }

        public string Operation { get; set; }

        public T Value { get; set; }

        public string ValueType { get; set; }

        /// <summary>| 或关系 & 与关系 ，默认为与 ，先或再与（||&&）</summary>
        public string QueryType { get; set; }

        /// <summary>查询条件是In的组合查询EntApp4.0表的instanceId;待办和已办all; 待办undo;已办done</summary>
        public string InstanceType { get; set; }

    }

    public class QueryParameter
    {
        private object _val;
        public object Value
        {
            get
            {
                return this._val;
            }
        }
        public QueryParameter(object val)
        {
            this._val = val;
        }
        public static explicit operator QueryParameter(string value)
        {
            return new QueryParameter(value);
        }
        public static implicit operator QueryParameter(DBNull value)
        {
            return new QueryParameter(value);
        }
        public static implicit operator QueryParameter(bool value)
        {
            return new QueryParameter(value);
        }
        public static implicit operator QueryParameter(byte value)
        {
            return new QueryParameter(value);
        }
        public static implicit operator QueryParameter(int value)
        {
            return new QueryParameter(value);
        }
        public static implicit operator QueryParameter(long value)
        {
            return new QueryParameter(value);
        }
        public static implicit operator QueryParameter(short value)
        {
            return new QueryParameter(value);
        }
        public static implicit operator QueryParameter(float value)
        {
            return new QueryParameter(value);
        }
        public static implicit operator QueryParameter(double value)
        {
            return new QueryParameter(value);
        }
        public static implicit operator QueryParameter(decimal value)
        {
            return new QueryParameter(value);
        }
        public static implicit operator QueryParameter(Guid value)
        {
            return new QueryParameter(value);
        }
        public static implicit operator QueryParameter(DateTime value)
        {
            return new QueryParameter(value);
        }
        public static implicit operator QueryParameter(byte[] value)
        {
            return new QueryParameter(value);
        }
    }
}
